package net.xyuu.config;

import java.io.IOException;
import java.util.ArrayList;

import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.data.mapping.PersistentEntity;
import org.springframework.data.rest.webmvc.config.RepositoryRestMvcConfiguration;
import org.springframework.data.rest.webmvc.mapping.Associations;
import org.springframework.data.web.HateoasPageableHandlerMethodArgumentResolver;
import org.springframework.hateoas.MediaTypes;
import org.springframework.hateoas.ResourceSupport;
import org.springframework.hateoas.mvc.TypeConstrainedMappingJackson2HttpMessageConverter;
import org.springframework.http.HttpInputMessage;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageNotReadableException;

import com.fasterxml.jackson.databind.JavaType;

import net.xyuu.entity.BatchEntity;

@Configuration
public class DataRestConfig extends RepositoryRestMvcConfiguration {

	/**
	 * 设置页面分页从1开始
	 */
	@Override
	public HateoasPageableHandlerMethodArgumentResolver pageableResolver() {
		HateoasPageableHandlerMethodArgumentResolver resolver = super.pageableResolver();
		resolver.setOneIndexedParameters(true);
		return resolver;
	}

	@Override
	public Associations associationLinks() {
		return new Associations(resourceMappings(), config()) {
			/**
			 * 设置显示所有实例ID
			 */
			@Override
			public boolean isIdExposed(PersistentEntity<?, ?> entity) {
				return true;
			}
		};
	}

	@Override
	public TypeConstrainedMappingJackson2HttpMessageConverter halJacksonHttpMessageConverter() {
		ArrayList<MediaType> mediaTypes = new ArrayList<MediaType>();
		mediaTypes.add(MediaTypes.HAL_JSON);
		if (config().useHalAsDefaultJsonMediaType()) {
			mediaTypes.add(MediaType.APPLICATION_JSON);
		}
		int order = config().useHalAsDefaultJsonMediaType() ? Ordered.LOWEST_PRECEDENCE - 10
				: Ordered.LOWEST_PRECEDENCE - 1;
		TypeConstrainedMappingJackson2HttpMessageConverter converter = new ResourceSupportHttpMessageConverter(order);
		converter.setObjectMapper(halObjectMapper());
		converter.setSupportedMediaTypes(mediaTypes);
		return converter;
	}

	private static class ResourceSupportHttpMessageConverter extends TypeConstrainedMappingJackson2HttpMessageConverter
			implements Ordered {

		private final int order;
		
		@Override
		protected Object readInternal(Class<?> clazz, HttpInputMessage inputMessage)
				throws IOException, HttpMessageNotReadableException {
			JavaType javaType = getJavaType(clazz, null);
			javaType = objectMapper.getTypeFactory().constructParametricType(BatchEntity.class,javaType);
			return objectMapper.readValue(inputMessage.getBody(), javaType);
		}

		public ResourceSupportHttpMessageConverter(int order) {
			super(ResourceSupport.class);
			this.order = order;
		}

		@Override
		public int getOrder() {
			return order;
		}
	}
}
